package com.seestech.sell.web.api.httpTask;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.seestech.sell.common.annotation.CheckFixedParamValue;
import com.seestech.sell.common.annotation.CheckMinMaxParamValue;
import com.seestech.sell.common.annotation.NotNullParam;
import com.seestech.sell.common.config.ApplicationConfig;
import com.seestech.sell.common.utils.*;
import com.seestech.sell.domain.model.*;
import com.seestech.sell.domain.model.pay.WeichatOrderResult;
import com.seestech.sell.domain.model.pay.WeichatRefundResult;
import com.seestech.sell.service.*;
import com.seestech.sell.service.pay.AlipayService;
import com.seestech.sell.service.pay.WeichatPayService;
import com.seestech.sell.web.SuperController;
import com.seestech.sell.web.pay.OrderResult;
import org.apache.commons.collections.map.HashedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static java.awt.SystemColor.info;
import static org.apache.coyote.http11.Constants.a;

/**
 * Created by idiot on 2017/6/23.
 */
@RestController
@RequestMapping(value = "api/httpTask/sellTask")
public class SellTask extends SuperController {
    private static Logger logger = LoggerFactory.getLogger(SellTask.class);

    @Resource
    private IAgentService agentService;
    @Resource
    private IShelfService shelfService;
    @Resource
    private IShelfDetailService shelfDetailService;
    @Resource
    private IOrderService orderService;
    @Resource
    private IRecorderService recorderService;
    @Resource
    private WeichatPayService weichatPayService;
    @Resource
    private AlipayService alipayService;
    @Resource
    private IGoodsService goodsService;
    @Resource
    private ICustomerService customerService;
    @Resource
    private ApplicationConfig applicationConfig;
    @Resource
    private IRefundService refundService;
    @Resource
    private RestTemplate restTemplate;
    @Resource
    private ICompanyPayService companyPayService;


    /**
     * @description  根据终端编号获取对应的货架信息
     * @param agentCode
     * @return
     */
    @NotNullParam(params = {"agentCode"})
    @RequestMapping(value = "getShelfByAgentCode.json")
    public Object getShelfByAgentCode(String agentCode){
        logger.info("根据终端编号获取对应的货架信息================>>>>>>>>开始");
        ResultBean<Object> resultBean;
        //根据agentCode获取终端信息
        Agent agent = agentService.getAgentByAgentCode(agentCode);
        if(agent == null){
            logger.error("根据终端编号获取对应的货架信息==============>>>>>无效的参数agentCode");
            resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数agentCode", false);
        }else {
            resultBean = getShelfByIds(agent.getShelfId(), agent.getSecondaryShelfId(), agent.getAgentId(), agent.getUniqueCode());
        }
        logger.info("根据终端编号获取对应的货架信息================>>>>>>>>结束");
        return resultBean;
    }


    /**
     * @description  根据终端编号获取该终端的库存  按照产品的种类顺序
     * @param agentCode
     * @return
     */
    @NotNullParam(params = {"agentCode"})
    @RequestMapping(value = "getStockByAgentCode.json")
    public Object getStockByAgentCode(String agentCode){
        logger.info("根据终端编号获取该终端的库存================>>>>>>>>开始");
        ResultBean<Object> resultBean;
        //根据终端编号获取终端信息
        Agent agent = agentService.getAgentByAgentCode(agentCode);
        if(agent == null){
            logger.error("根据终端编号获取该终端的库存==============>>>>>无效的参数agentCode");
            resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数agentCode", false);
        }else {
            //根据终端信息中的货架编号获取货架信息  产品的顺序
            Shelf shelf = shelfService.getShelfByShelfId(agent.getShelfId());
            //获取货架的产品信息
            String[] products = new String[shelf.getAmount()];
            if (shelf.getProducts() != null && !"".equals(shelf.getProducts())) {
                products = shelf.getProducts().split(";");
            }
            //获取货架的产品库存信息
            String[] stockses = new String[shelf.getAmount()];
            if (shelf.getStocks() != null && !"".equals(shelf.getStocks())) {
                stockses = shelf.getStocks().split(";");
            }

            //根据终端编号获取库存记录信息中最新的一条记录没有就返回0
            int[] stocks;

            //获取最新的库存记录
            stocks = getLeftStock(agent.getAgentId(), shelf.getShelfId(), null, stockses);

            Map<String,Object> map = new HashedMap();
            map.put("stocks", stocks);              //现有库存  对应商品种类
            map.put("products", products);          //商品种类
            map.put("totals", stockses);            //商品总库存
            resultBean = ResponseUtils.initResultBean(map, Constants.ResponseCode.success, "成功", true);
        }
        logger.info("根据终端编号获取该终端的库存================>>>>>>>>结束");
        return resultBean;
    }


    /**
     * @description  下订单
     * @param agentCode     终端编号
     * @param goodsId       商品编号
     * @param price         价格
     * @param channel       支付渠道    1微信  2支付宝  3积分
     * @param amount        数量
     * @param index         商品种类的下标 0 表示第一个
     * @return
     */
    @NotNullParam(params = {"agentCode", "goodsId", "price", "channel", "amount", "index"})
    @RequestMapping(value = "preOrder.json")
    public Object preOrder(String agentCode, Long goodsId, double price,
                           @CheckFixedParamValue(name = "channel", value = {"1","2", "3"})int channel,
                           @CheckMinMaxParamValue(name = "amount", min = 1) int amount,
                           @CheckMinMaxParamValue(name = "index", min = 0) int index){
        logger.info("下订单================>>>>>>>>开始");
        ResultBean<Object> resultBean;
        //获取终端信息
        Agent agent = agentService.getAgentByAgentCode(agentCode);
        if(agent == null){
            logger.error("下订单==============>>>>>无效的参数agentCode"+agentCode);
            resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数agentCode", false);
        }else {
            //根据终端信息中的货架编号获取货架信息  产品的顺序
            Shelf shelf = shelfService.getShelfByShelfId(agent.getShelfId());
            //获取货架的产品信息
            String[] products = new String[shelf.getAmount()];
            if (shelf.getProducts() != null && !"".equals(shelf.getProducts())) {
                products = shelf.getProducts().split(";");
            }

            //判断index是否有效
            if(index >= products.length){
                logger.error("下订单==============>>>>>无效的参数index,index超出商品的种类数量");
                return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数index:"+index, false);
            }

            //判断goodsId和index是否符合
            if(!products[index].equals(String.valueOf(goodsId))){
                logger.error("下订单==============>>>>>无效的参数goodsId,商品对应的index与goodsId不符["+goodsId +"*"+ index+"]");
                return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数goodsId,商品的index与goodsId不符", false);
            }

            //判断price 是否合格
            double newPrice = Double.parseDouble(new DecimalFormat("0.00").format(price));
            if(price <= 0 || price != newPrice){
                logger.error("下订单==============>>>>>无效的参数price:"+price);
                return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数price:"+price+"(最大两位小数且不小于0)", false);
            }

            //获取商品信息
            Goods goods = goodsService.getGoodsByGoodsId(goodsId);
            if(goods == null){
                logger.error("下订单==============>>>>>无效的参数goodsId"+goodsId);
                return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数goodsId", false);
            }
            int remain = getGoodsRemain(agent.getAgentId(), agent.getShelfId(), goodsId);
            if(remain == 0){
                logger.error("下订单==============>>>>>无效的参数goodsId，库存不足");
                return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数goodsId,商品库存不足", false);
            }
            if(amount > remain){
                logger.error("下订单==============>>>>>无效的参数amount，库存不足"+amount);
                return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数amount,商品库存不足", false);
            }
            // 根据终端编号管理终端分组  获取企业支付信息
            CompanyPay companyPay = companyPayService.getCompanyPayByAgentId(agent.getAgentId());
            if (companyPay == null){
                logger.error("下订单==============>>>>>企业支付配置不存在");
                return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "企业支付配置不存在", false);
            }
            // 判断企业支付配置 中的微信或者支付宝是否开启  没开启返回错误提示信息
            if (companyPay != null && (companyPay.getOpenWechatPay() == 0 && companyPay.getOpenAlipay() == 0)){
                logger.error("下订单==============>>>>>企业支付配置未开启");
                return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "企业支付配置未开启", false);
            }
            //交易结果信息
            OrderResult orderResult;
            //生成订单号 添加订单信息
            Long orderId = IdGen.get().nextId();
            //根据类型调用支付宝|微信获取交易链接  返回交易链接和订单号     检测是否开启微信支付
            if(channel == 1 && companyPay.getOpenWechatPay() == 1){
                //微信支付下单
                WeichatOrderResult result = weichatPayService.orderResult(companyPay.getWechatAppId(),
                        companyPay.getWechatMchId(), companyPay.getWechatMchKey(),
                        companyPay.getWechatNotifyUrl(), String.valueOf(orderId), goods.getName(), price);
                if(result.getReturn_code().equals("SUCCESS") && "SUCCESS".equals(result.getResult_code())){
                    //设置订单返回值
                    orderResult = new OrderResult(result.getCode_url(), channel, true, String.valueOf(orderId));
                    addOrder(orderId, agent.getAgentId(), agent.getShelfId(), companyPay.getCompanyId(),
                            channel, goodsId, goods.getName(), price, amount, index);
                    resultBean = ResponseUtils.initResultBean(orderResult, Constants.ResponseCode.success, "成功", true);
                }else {
                    //生成微信交易链接失败
                    orderResult = new OrderResult(null, channel, false, String.valueOf(orderId));
                    resultBean = ResponseUtils.initResultBean(orderResult, Constants.ResponseCode.error, "生成微信交易链接失败", false);
                }
            }else if(channel == 2 && companyPay.getOpenAlipay() == 1){   //  支付宝下单  检测是否开启支付宝支付
                //支付宝支付下单、
                try {
                    AlipayTradePrecreateResponse result = alipayService.preOrder(companyPay.getAlipayAppId(),
                            companyPay.getAlipayPublicKey(), companyPay.getAlipayPrivateKey(),
                            companyPay.getAlipaySignType(), companyPay.getAlipayNotifyUrl(),
                            String.valueOf(orderId), price, goods.getName());
                    if(result.getCode().equals("10000")){ //返回CODE 为成功
                        //设置订单返回值
                        orderResult = new OrderResult(result.getQrCode(), channel, true, String.valueOf(orderId));
                        addOrder(orderId, agent.getAgentId(), agent.getShelfId(), companyPay.getCompanyId(),
                                channel, goodsId, goods.getName(), price, amount, index);
                        resultBean = ResponseUtils.initResultBean(orderResult, Constants.ResponseCode.success, "成功", true);
                    }else {
                        orderResult = new OrderResult(null, channel, false, String.valueOf(orderId));
                        resultBean = ResponseUtils.initResultBean(orderResult, Constants.ResponseCode.error, "生成支付宝交易链接失败", false);
                    }
                } catch (AlipayApiException e) {
                    logger.error("调用支付宝生成交易链接失败。。。。。原因："+e.getMessage());
                    resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "生成支付宝交易链接失败", false);
                }
            }else if(channel == 3){
                //积分下单
                orderResult = new OrderResult(null, channel, true, String.valueOf(orderId));
                addOrder(orderId, agent.getAgentId(), agent.getShelfId(), companyPay.getCompanyId(),
                        channel, goodsId, goods.getName(), price, amount, index);
                resultBean = ResponseUtils.initResultBean(orderResult, Constants.ResponseCode.success, "成功", true);
            }else {
                //无效的参数channel
                resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数channel", false);
            }
        }
        logger.info("下订单================>>>>>>>>结束");
        return resultBean;
    }


    //根据订单号查询交易情况
    @NotNullParam(params = {"orderId"})
    @RequestMapping(value = "getOrderByOrderId.json")
    public Object getOrderByOrderId(Long orderId) {
        logger.info("根据订单号查询交易情况================>>>>>>>>开始");
        ResultBean<Object> resultBean;
        //根据订单号查询订单状态信息
        Order order = orderService.getOrderByOrderId(orderId);
        if (order == null) {
            logger.error("根据订单号查询交易情况==============>>>>>无效的参数orderId");
            resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数orderId", false);
        } else {
            //把long类型的转换为字符串
            JSONObject object = JsonUtils.parseObject(order);
            resultBean = ResponseUtils.initResultBean(object, Constants.ResponseCode.success, "成功", true);
        }
        logger.info("根据订单号查询交易情况================>>>>>>>>结束");
        return resultBean;
    }


    //补货接口
    // @param  json字符串 {"products": ["876738514488655872","878546136938315776"],"stocks": [10,20],"total":30}
    @NotNullParam(params = {"agentCode"})
    @RequestMapping(value = "restock.json")
    public Object restock(String agentCode, String data){
        logger.info("补货接口================>>>>>>>>开始");
        ResultBean<Object> resultBean;
        //获取终端信息
        Agent agent = agentService.getAgentByAgentCode(agentCode);
        if(agent == null){
            logger.error("补货接口==============>>>>>无效的参数agentCode");
            resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数agentCode", false);
        }else {
            //根据货架的products 和  参数products 对比
            JSONObject dataObject = JSON.parseObject(data);

            //判断data参数是否合格
            if(dataObject == null){
                logger.error("补货接口=========>>>>>无效的参数data======>>>>>");
                return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数data", false);
            }

            //data中是否包含products|stocks|total
            if(!dataObject.containsKey("products") || !dataObject.containsKey("stocks") || !dataObject.containsKey("total")){
                logger.error("补货接口=========>>>>>无效的参数data======>>>>>必须包含products|stocks|total");
                return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数data", false);
            }

            //判断stocks 的和  是否和 total相同
            Object[] arr = dataObject.getJSONArray("stocks").toArray();
            int sum = 0;
            for (int i = 0; i < arr.length; i++) {
                sum += Integer.parseInt(String.valueOf(arr[i]));
            }
            if(sum != dataObject.getIntValue("total")){
                logger.error("补货接口=========>>>>>无效的参数data======>>>>>stocks之和和total不相等");
                return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数data,stocks之和和total不相等", false);
            }

            //根据终端编号获取货架信息  满库存时总量
            Shelf shelf = shelfService.getShelfByShelfId(agent.getShelfId());
            if(shelf == null){
                logger.error("补货接口==============>>>>>无效的参数shelfId");
                return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "该终端绑定的货架信息有误", false);
            }
            //获取货架的产品库存信息
            String[] stocks = new String[shelf.getAmount()];
            if (shelf.getStocks() != null && !"".equals(shelf.getStocks())) {
                stocks = shelf.getStocks().split(";");
            }
            //获取货架的产品信息
            String[] products = new String[shelf.getAmount()];
            if (shelf.getProducts() != null && !"".equals(shelf.getProducts())) {
                products = shelf.getProducts().split(";");
            }

            Object[] array = dataObject.getJSONArray("products").toArray();
            if(Arrays.equals(array, products)){
                //获取货架的总库存  与当前库存对比
                if(shelf.getTotal() < dataObject.getIntValue("total")){
                    logger.error("补货接口=========>>>>>无效的参数total======>>>>>超过货架的容量");
                    return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数total", false);
                }
                //记录信息
                Recorder recorder = new Recorder();
                recorder.setAgentId(agent.getAgentId());
                recorder.setShelfId(shelf.getShelfId());
                recorder.setOperate(1);     //补货   增
                recorder.setBatchNumber(StringUtils.generateUUID());        //设置批次号
                //更新商品记录信息
                if(recorderService.modify(products, recorder, arr, stocks)){
                    resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.success, "成功", true);
                }else
                    resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "修改库存失败，请重试", false);
            }else {
                logger.error("补货接口==============>>>>>无效的参数products\n【"+Arrays.toString(products)+"】【"+JSON.parseObject(data).getJSONArray("products")+"】");
                resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数products", false);
            }
        }
        logger.info("补货接口================>>>>>>>>结束");
        return resultBean;
    }


    //出货状态接口
    @NotNullParam(params = {"agentCode", "orderId", "saleStatus"})
    @RequestMapping(value = "saleStatus.json")
    public Object saleStatus(String agentCode, Long orderId,
                             @CheckFixedParamValue(name = "saleStatus", value = {"1","-1"})int saleStatus){
        logger.info("出货状态更新接口================>>>>>>>>开始");
        ResultBean<Object> resultBean;
        //根据订单编号查询订单信息   对比agentCode所查询出来的agentId 是否一致
        Agent agent = agentService.getAgentByAgentCode(agentCode);
        if(agent == null) {
            logger.error("出货状态更新接口=============>>>>>>>>无效的参数agentCode");
            return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数agentCode", false);
        }
        Order order = orderService.getOrderByOrderId(orderId);
        if(order == null){
            logger.error("出货状态更新接口=============>>>>>>>>无效的参数orderId");
            return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数orderId", false);
        }
        if(order.getAgentId().equals(agent.getAgentId())){
            logger.info("出货状态更新接口=============>>>>>>>>更新订单出货状态");
            order.setSaleStatus(saleStatus);
            orderService.update(order);
            if(saleStatus == 1){
                //减库存
                if(reduceStock(order.getAgentId(), order.getIdx(), order.getAmount(), order)){
                    resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.success, "更新订单出货状态成功", true);
                }else
                    resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "更新订单出货状态失败", false);
            }else {
                resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.success, "更新订单出货状态成功", true);
            }
        }else {
            logger.error("出货状态更新接口=============>>>>>>>>agentId与订单中的不符合");
            resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "订单中的终端编号与预期不符", false);
        }
        logger.info("出货状态更新接口================>>>>>>>>完成");
        return resultBean;
    }


    //根据customerId获取客户信息
    @NotNullParam(params = "customerId")
    @RequestMapping(value = "getCustomerByOrderId.json")
    public Object getCustomerByOrderId(String customerId){
        logger.info("根据orderId获取用户信息========================>>>>>>>开始");
        //根据customerId获取customer信息   返回
        Customer customer = customerService.getCustomerByCustomerId(customerId);
        logger.info("根据orderId获取用户信息========================>>>>>>>完成");
        return ResponseUtils.initResultBean(customer, Constants.ResponseCode.success, "成功", true);
    }


    //绑定客户信息接口
    @NotNullParam(params = {"customerId", "phone", "channel"})
    @RequestMapping(value = "bindCustomer.json")
    public Object bindCustomer(String customerId, String phone,
                               @CheckFixedParamValue(name = "channel", value = {"1","2"})int channel){
        logger.info("绑定客户信息接口========================>>>>>>>开始");
        Customer customer = customerService.getCustomerByCustomerId(customerId);
        if(customer != null){
            logger.info("绑定客户信息接口========================>>>>>>>客户信息已经存在");
            return ResponseUtils.initResultBean(null, Constants.ResponseCode.success, "客户信息已经存在", true);
        }
        //新增客户信息
        customer = new Customer();
        customer.setCustomerId(customerId);     //用户支付账号
        customer.setPhone(phone);               //电话号码
        customer.setChannel(channel);           //支付渠道
        //根据customerId获取订单信息   初始化 交易次数  和历史交易金额
        HashMap<String, Object> map = orderService.getOrdersByCustomerId(customerId);
        if(map != null){
            logger.info("设置交易次数以及历史交易金额");
            customer.setCount(Integer.parseInt(String.valueOf(map.get("count"))));
            customer.setTotalFee(Double.parseDouble(String.valueOf(map.get("totalFee"))));
        }
        customerService.insert(customer);       //新增
        logger.info("绑定客户信息接口========================>>>>>>>结束");
        return ResponseUtils.initResultBean(null, Constants.ResponseCode.success, "成功", true);
    }

    /**
     * @description  根据手机号查询用户积分信息
     * @param phone
     * @return
     */
    @NotNullParam(params = {"phone"})
    @RequestMapping(value = "getCustomerByPhone.json")
    public Object getCustomerByPhone(String phone){
        ResultBean<Object> resultBean;
        List<Customer> customers = customerService.getCustomersByPhone(phone);
        resultBean = ResponseUtils.initResultBean(customers, Constants.ResponseCode.success, "成功", true);
        resultBean.setTotalCount(customers == null ? 0 :customers.size());
        return resultBean;
    }

    /**
     * @description   自动退款
     * @param orderId       订单编号
     * @param refundFee     退款金额    可选
     * @param reason        退款原因
     * @note   退积分接口  http://test-api.shewngroup.com/gateway.cgi?mod=wine.refund&v=1
    字段，card_id--用户卡号，order_number--订单编号，time--当前时间秒数，code--校验码
    code：这之前差不多验证方式，card_id + order_number + (time - 9999),对此字符串倒序，再md5加密
    成功退积分，返回：{"status":"success"}否则：{"status":"success","message":"xxxx"}
     * @return
     */
    @NotNullParam(params = {"orderId", "reason"})
    @RequestMapping(value = "refund.json")
    public Object refund(Long orderId,
                         @RequestParam(defaultValue = "0") double refundFee,
                         String reason){
        ResultBean<Object> resultBean;
        //根据订单编号获取订单信息
        Order order = orderService.getOrderByOrderId(orderId);
        if(order == null){
            logger.error("自动退款接口==============>>>>>无效的参数orderId");
            resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数orderId", false);
        }else {
            //如果订单没有交易成功   无法退款
            if(order.getSuccess() != 1){
                logger.error("自动退款接口==============>>>>>订单未支付，无法退款");
                return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "订单未支付，无法退款", false);
            }
            //当退款金额 没有传递  默认为0
            if(refundFee != 0){
                //判断 refundFee 是否合格   大于0  小数位不超过两位
                double newPrice = Double.parseDouble(new DecimalFormat("0.00").format(refundFee));
                if(refundFee <= 0 || refundFee != newPrice){
                    logger.error("自动退款接口==============>>>>>无效的参数refundFee:"+refundFee);
                    return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数refundFee:"+refundFee+"(最大两位小数且不小于0)", false);
                }
                //对比交易金额和退款金额 退款金额<=交易金额
                if(refundFee > order.getPrice()){
                    logger.error("自动退款接口==============>>>>>无效的参数refundFee:"+refundFee);
                    return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数refundFee:"+refundFee+"(不能超过订单交易金额)", false);
                }
            }else {
                logger.info("自动退款接口==============>>>>>退款金额为订单交易金额===>>"+order.getPrice());
                refundFee = order.getPrice();   //设置订单交易金额
            }
            Long refundId = IdGen.get().nextId();
            Refund info = new Refund();
            info.setRefundId(refundId);   //设置主键
            info.setReason(reason);
            info.setChannel(order.getChannel());
            info.setRefundFee(refundFee);
            info.setTotalFee(order.getPrice());
            info.setOrderId(orderId);
            // 根据订单编号 关联企业信息   加载企业支付配置信息
            CompanyPay companyPay = companyPayService.getCompanyPayByOrderId(info.getOrderId());
            if (companyPay == null){
                logger.error("自动退款接口==============>>>>>企业支付配置不存在");
                return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "企业支付配置不存在", false);
            }
            // 判断企业支付配置 中的微信或者支付宝是否开启  没开启返回错误提示信息
            if (companyPay != null && (
                    (companyPay.getOpenWechatPay()== null || companyPay.getOpenWechatPay() == 0)
                    && (companyPay.getOpenAlipay() == null || companyPay.getOpenAlipay() == 0)
                    && (companyPay.getOpenCodePay() == null || companyPay.getOpenCodePay() == 0))){
                logger.error("自动退款接口==============>>>>>企业支付配置未开启");
                return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "企业支付配置未开启", false);
            }
            //开始退款  微信退款   检测是否开启微信退款
            if(order.getChannel() == 1 && companyPay.getOpenWechatPay() == 1){
                //微信退款
                logger.info("微信自动退款请求==================>>>>>>>>>>>>开始");
                String certPath = FileUtils.getWindowsPath(FileUtils.addPathSeparate(applicationConfig.getBaseDirectory(),
                        companyPay.getWechatCertPath()));
                WeichatRefundResult result = weichatPayService.refundResult(companyPay.getWechatAppId(),
                        companyPay.getWechatMchId(), companyPay.getWechatMchKey(),String.valueOf(refundId),
                        String.valueOf(info.getOrderId()), info.getRefundFee(), info.getRefundFee(), certPath);
                if("SUCCESS".equals(result.getReturn_code()) && "SUCCESS".equals(result.getResult_code())){
                    info.setSuccess(1);     //微信退款成功
                    updateOrder(info.getOrderId()); //修改订单信息
                    resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.success, "退款成功", true);
                }else {
                    info.setSuccess(0);
                    resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "退款失败", false);
                }
                logger.debug(JSON.toJSONString(result));
                logger.info("微信自动退款请求==================>>>>>>>>>>>>结束");
            }else if(order.getChannel() == 2 && companyPay.getOpenAlipay() == 1){   // 支付宝退款  检测是否开启支付宝退款
                //支付宝退款
                logger.info("支付宝自动退款请求==================>>>>>>>>>>>>开始");
                AlipayTradeRefundResponse result = null;
                try {
                    result = alipayService.refundResponse(companyPay.getAlipayAppId(), companyPay.getAlipayPublicKey(),
                            companyPay.getAlipayPrivateKey(), companyPay.getAlipaySignType(),
                            String.valueOf(info.getOrderId()), info.getRefundFee(), info.getReason());
                } catch (AlipayApiException e) {
                    logger.error("支付宝申请退款失败。错误原因："+e.getMessage());
                    info.setSuccess(0);
                }
                if(result != null && "10000".equals(result.getCode())){
                    info.setSuccess(1);     //支付宝退款成功
                    updateOrder(info.getOrderId()); //修改订单信息
                    resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.success, "退款成功", true);
                }else {
                    info.setSuccess(0);
                    resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "退款失败", false);
                }
                logger.info("支付宝自动退款请求==================>>>>>>>>>>>>结束");
            }else if(order.getChannel() == 3 && companyPay.getOpenCodePay() == 1){  // 积分退款  检测是否开启积分退款
                logger.info("积分退款请求==================>>>>>>>>>>>>开始");
                long time = System.currentTimeMillis()/1000;
                String initCode = order.getCardId() + order.getOrderNumber() + (time-9999);
                String code = EncodeMD5.GetMD5Code(new StringBuffer(initCode).reverse().toString());
                //发起退积分请求  获取返回结果
                JSONObject jsonObject = new JSONObject();
                MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
                paramMap.add("card_id", order.getCardId());
                paramMap.add("order_number", order.getOrderNumber());
                paramMap.add("time", time);
                paramMap.add("code", code);
                jsonObject = restTemplate.postForObject(companyPay.getCodeRefundUrl(), paramMap, JSONObject.class);
                if ("success".equals(jsonObject.getString("status"))){
                    info.setSuccess(1);     //积分退款成功
                    updateOrder(info.getOrderId()); //修改订单信息
                    resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.success, "退积分成功", true);
                }else {
                    info.setSuccess(0);
                    resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "退积分失败", false);
                }
                logger.info("积分退款请求==================>>>>>>>>>>>>结束");
            }else {
                info.setSuccess(0);
                logger.error("该订单无法退款......channel"+info.getChannel());
                resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "该订单无法退款", false);
            }
            refundService.insert(info);         //新增
        }
        return resultBean;
    }

    /**
     * @description  扫码结果回调接口    当支付渠道为积分时  扫用户的积分码  回传结果
     *               该接口是红酒柜系统  佘恩国际   需要的支付手段
     * @param code      支付码
     * @param orderId   订单编号
     * @return
     */
    @RequestMapping(value = "scanCode.json")
    @NotNullParam(params = {"code", "orderId"})
    public Object scanCode(String code, Long orderId){
        logger.info("扫码结果回调接口=================>>>>>>>开始");
        ResultBean<Object> resultBean;
        //获取订单信息
        Order order = orderService.getOrderByOrderId(orderId);
        //订单存在  而且  订单状态有效  以及  订单处于处理中
        if(order == null || order.getStatus() != 1 || order.getSuccess() != 0){
            logger.info("扫码结果回调接口=================>>>>>>>订单异常【orderId】"+orderId);
            return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数orderId"+orderId, false);
        }
        if(order.getChannel() != 3){
            logger.info("扫码结果回调接口=================>>>>>>>订单异常【支付渠道不是积分支付】");
            return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "该订单非积分支付", false);
        }
        // 根据订单编号 关联企业信息   加载企业支付配置信息
        CompanyPay companyPay = companyPayService.getCompanyPayByOrderId(orderId);
        if (companyPay == null){
            return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "企业支付配置不存在", false);
        }
        // 判断企业支付配置 是否开启  没开启返回错误提示信息
        if (companyPay != null &&
                (companyPay.getOpenCodePay() == null || companyPay.getOpenCodePay() == 0)){
            return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "企业积分支付配置未开启", false);
        }
        Agent agent = agentService.getAgentByAgentId(order.getAgentId());
        //获取扫码结果
        String[] result = code.split(",");
        if(result == null || result.length != 4){
            logger.info("扫码结果回调接口=================>>>>>>>无效的支付码"+code);
            return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的支付码", false);
        }
        //前三组
        String a = code.substring(0, code.lastIndexOf(","));
        //对a进行反转字符串
        String b = new StringBuffer(a).reverse().toString();
        //获取时间戳
        long time = Long.parseLong(result[2]);
        //b 加上 分隔符  加上  时间戳减去9999
        String c = b+","+(time - 9999);
        //获取加密后的c   也就是校验码  跟code的第四组对比
        String d = EncodeMD5.GetMD5Code(c);
        //验证是否有效
        if(d.equals(result[3])){
            logger.info("扫码结果回调接口=================>>>>>>>使用积分支付开始");
            //有效情况下   扣减积分   获取支付结果
            MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
            paramMap.add("transaction_type", "defray.wine");
            paramMap.add("point", order.getPrice());
            paramMap.add("card_id", result[0]);
            paramMap.add("region", agent.getAreaName());
            paramMap.add("product_number", order.getGoodsCode());
            paramMap.add("machine_number", agent.getAgentCode());
            paramMap.add("product_name", order.getGoodsName());
            JSONObject jsonObject = restTemplate.postForObject(companyPay.getScanCodeUrl(), paramMap, JSONObject.class);
            logger.info(JSON.toJSONString(jsonObject));
            if("success".equals(jsonObject.getString("status"))){       //支付成功
                logger.info("扫码结果回调接口===============>>>>>>>>>支付成功");
                //更改订单信息
                Order info = new Order();
                info.setOrderId(orderId);   //设置主键
                info.setCardId(result[0]);  //设置积分卡号
                info.setSuccess(1);         //支付成功
                info.setOrderNumber(jsonObject.getJSONObject("data").getString("order_number"));
                orderService.update(info);
                //更新客户积分信息表
                customerService.modify(result[0], order.getPrice());
                resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.success, "积分码支付成功", true);
            }else {
                logger.error("扫码结果回调接口===============>>>>>>>>>积分码支付失败==="+jsonObject.getString("message"));
                resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "积分码支付失败", true);
            }
        }else{
            logger.info("扫码结果回调接口=================>>>>>>>支付积分码验证失败"+d+"**"+Arrays.toString(result));
            resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "支付积分码验证失败", false);
        }
        logger.info("扫码结果回调接口=================>>>>>>>结束");
        return resultBean;
    }


    /**
     * @description   切换货架信息接口
     * @param agentCode
     * @return
     */
    @RequestMapping(value = "changeShelf.json")
    @NotNullParam(params = {"agentCode"})
    public Object changeShelf(String agentCode){
        logger.info("切换货架信息接口================>>>>>>>>开始");
        ResultBean<Object> resultBean;
        //获取终端信息
        Agent agent = agentService.getAgentByAgentCode(agentCode);
        if(agent == null) {
            logger.error("切换货架信息接口=============>>>>>>>>无效的参数agentCode"+agentCode);
            return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数agentCode", false);
        }else {
            //对比终端是否是这个备用的货架编号
            if(agent.getSecondaryShelfId() == null){
                logger.error("切换货架信息接口=============>>>>>>>>该终端没有备用货架");
                resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "该终端没有备用货架", false);
            }else{
                logger.info("切换货架信息接口=============>>>>>>>>更换终端主要货架信息"+agent.getAgentName());
                //更换终端货架信息
                Agent info = new Agent();
                info.setAgentId(agent.getAgentId());
                info.setShelfId(agent.getSecondaryShelfId());      //切换备用货架为主要货架
                info.setSecondaryShelfId(0l);   //置空备用货架
                agentService.update(info);  //修改
                //更新最新库存信息   置空 0    根据终端id获取终端的库存信息
                updateRecorder(agent.getAgentId(), agent.getSecondaryShelfId());
                resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.success, "成功", true);
            }
        }
        logger.info("切换货架信息接口=============>>>>>>>>结束");
        return resultBean;
    }


    /**
     * @description  获取备用货架信息
     * @param agentCode
     * @param secondaryShelfId
     * @return
     */
    @NotNullParam(params = {"agentCode", "secondaryShelfId"})
    @RequestMapping(value = "getSecondaryShelf.json")
    public Object getSecondaryShelf(String agentCode, Long secondaryShelfId){
        logger.info("获取备用货架信息================>>>>>>>>开始");
        ResultBean<Object> resultBean;
        //获取终端信息
        Agent agent = agentService.getAgentByAgentCode(agentCode);
        if(agent == null) {
            logger.error("获取备用货架信息=============>>>>>>>>无效的参数agentCode"+agentCode);
            return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数agentCode", false);
        }else {
            if(agent.getSecondaryShelfId() == null || !agent.getSecondaryShelfId().equals(secondaryShelfId)){
                logger.error("获取备用货架信息=============>>>>>>>>无效的参数secondaryShelfId"+secondaryShelfId);
                return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "终端没有该备用货架", false);
            }
            resultBean = getShelfByIds(secondaryShelfId, agent.getSecondaryShelfId(), agent.getAgentId(), agent.getUniqueCode());
        }
        logger.info("获取备用货架信息================>>>>>>>>结束");
        return resultBean;
    }


    /*******************************************************************************/

    //修改订单信息
    private void updateOrder(Long orderId){
        Order order = new Order();
        order.setOrderId(orderId);
        order.setSuccess(2);        //更改为退款
        orderService.update(order);
    }


    /**
     * @description  添加订单信息
     * @param orderId
     * @param agentId
     * @param channel
     * @param goodsId
     * @param goodsName
     * @param price
     * @param amount
     * @param index
     */
    private void addOrder(Long orderId, Long agentId, Long shelfId, Long companyId, int channel, Long goodsId,
                          String goodsName, double price, int amount, int index){
        Order order = new Order();
        order.setOrderId(orderId);
        order.setAgentId(agentId);
        order.setShelfId(shelfId);
        order.setCompanyId(companyId);
        order.setChannel(channel);
        order.setGoodsId(goodsId);
        order.setGoodsName(goodsName);
        order.setPrice(price);
        order.setAmount(amount);
        order.setIdx(index);
        orderService.insert(order);
    }

    /**
     * @description  减库存
     * @param agentId
     * @param index
     * @param amount
     */
    private boolean reduceStock(Long agentId, int index, int amount, Order order){
        logger.info("减库存==============>>>>>>>>>>>>>");
        //获取货架信息  以及货架上的商品信息
        Shelf shelf = shelfService.getShelfByShelfId(order.getShelfId());
        if(shelf == null){
            logger.error("减库存==============>>>>>无效的参数shelfId");
            return false;
        }
        //获取货架的产品总库存库存信息
        String[] stocks = new String[shelf.getAmount()];
        if (shelf.getStocks() != null && !"".equals(shelf.getStocks())) {
            stocks = shelf.getStocks().split(";");
        }

        //获取货架的产品信息
        String[] products = new String[shelf.getAmount()];
        if (shelf.getProducts() != null && !"".equals(shelf.getProducts())) {
            products = shelf.getProducts().split(";");
        }

        //获取当前库存记录信息
        Long goodsId = Long.parseLong(products[index]);

        int[] lefts;
        int remain = getGoodsRemain(agentId, shelf.getShelfId(), goodsId);
        //获取最新的库存记录
        lefts = getLeftStock(agentId, shelf.getShelfId(), null, stocks);

        if(remain != 0){
            //减库存
            lefts[index] = remain-amount;
            //记录信息
            String left = StringUtils.arrayToString(StringUtils.toStringArray(lefts), Constants.CsMessageSeperator.semicolon);
            Long recorderId = IdGen.get().nextId();
            Recorder recorder = new Recorder();
            recorder.setRecorderId(recorderId);
            recorder.setAgentId(agentId);
            recorder.setShelfId(shelf.getShelfId());
            recorder.setOperate(0);     //出货  减
            recorder.setGoodsId(Long.parseLong(products[index]));                //设置商品编号
            recorder.setAmount(remain-amount);                          //设置当前商品库存
            recorder.setTotal(Integer.parseInt(stocks[index]));                 //设置该商品在货架中的总库存
            recorder.setRemain(left);           //设置商品剩余库存
            recorder.setBatchNumber(StringUtils.generateUUID());        //设置批次号

            // recorder.setIsNew(1);                                       //新纪录

            //更新商品记录信息
            recorderService.insert(recorder);
            if(recorderService.getRecorderByRecorderId(recorderId) == null){
                //加入重试队列
                logger.error("添加商品记录信息失败,未查询到记录信息");
                return false;
            }
            return true;
        }else {
            logger.error("该商品的库存记录为空......");
            return false;
        }

    }

    //获取商品的现存量
    private int getGoodsRemain(Long agentId, Long shelfId, Long goodsId){
        List<Recorder> list = recorderService.getRecordersByIds(agentId, shelfId, goodsId);
        if(list != null && list.size() > 0){
            Recorder info = list.get(0);
            return info.getAmount() == null ? 0 : info.getAmount();
        }else return 0;
    }

    //获取最新的库存记录
    private int[] getLeftStock(Long agentId, Long shelfId, Long goodsId, String[] stockses){
        int[] stocks;
        List<Recorder> list = recorderService.getRecordersByIds(agentId, shelfId, goodsId);
        if(list != null && list.size() > 0){
            Recorder info = list.get(0);
            String remain = info.getRemain();
            //当剩余库存为空时  库存默认为0
            if(remain == null || "".equals(remain)){
                stocks = StringUtils.toIntArray(null, stockses.length);
            }else {
                stocks = StringUtils.stringToArray(new int[]{}, remain, Constants.CsMessageSeperator.semicolon);
            }
        }else {
            //不存在记录时 库存默认为0
            stocks = StringUtils.toIntArray(null, stockses.length);
        }
        return stocks;
    }

    //获取货架信息
    private ResultBean<Object> getShelfByIds(Long shelfId, Long secondaryShelfId, Long agentId, String uniqueCode){
        ResultBean<Object> resultBean;
        //根据终端信息中的货架编号获取货架信息  产品
        Shelf shelf = shelfService.getShelfByShelfId(shelfId);
        //根据货架编号获取货架详情信息 柜格名称  柜格价格  商品名  图片  商品价格
        List<ShelfDetail> shelfDetails = shelfDetailService.getShelfDetailsByShelfId(shelf.getShelfId());
        Map<String, Object> map = new HashMap<>();
        //把long类型的转换为字符串
        JSONArray object = JsonUtils.parseArray(shelfDetails, "image", "detailImage");
        map.put("grids", object);               //柜格信息
        map.put("shelfName", shelf.getName());  //货架名称
        map.put("layout", shelf.getLayout());   //布局
        map.put("total", shelf.getTotal());     //总量（可存放商品总量）
        map.put("amount", shelf.getAmount());   //占用柜格数量
        map.put("shelfId", String.valueOf(shelf.getShelfId())); //货架编号
        map.put("secondaryShelfId", String.valueOf(secondaryShelfId)); //备用货架编号
        String[] products = new String[shelf.getAmount()];
        if (shelf.getProducts() != null && !"".equals(shelf.getProducts())) {
            products = shelf.getProducts().split(";");
        }
        map.put("products", products);          //商品种类集合
        //把map转换成json字符串   用MD5加密  然后与终端中的uniqueCode比较
        String result = EncodeMD5.GetMD5Code(JSON.toJSONString(map));
        if(!result.equals(uniqueCode)){
            Agent info = new Agent();
            info.setAgentId(agentId);
            info.setUniqueCode(result);
            agentService.update(info); //修改终端  唯一标识
        }
        //map 子集合
        Map<String, Object> item = new HashMap<>();
        item.put("uniqueCode", result);     //唯一标识
        resultBean = ResponseUtils.initResultBean(map, Constants.ResponseCode.success, "成功", true);
        resultBean.setMap(item);
        return resultBean;
    }

    //更换货架初始化库存记录
    private void updateRecorder(Long agentId, Long secondaryShelfId){
        Map<String, Object> map = agentService.getGoodsInfo(agentId);
        if(map != null && map.size() > 0){
            String[] stocks = String.valueOf(map.get("stocks")).split(";");
            // String[] alrams = String.valueOf(map.get("alarms")).split(";");
            String[] remains = new String[]{};
            int[] remain = StringUtils.toIntArray(remains, stocks.length);
            //获取商品编号
            String[] goodsIds = String.valueOf(map.get("products")).split(";");
            Goods goods = goodsService.getGoodsByGoodsId(Long.parseLong(goodsIds[0]));
            if(goods != null){
                Recorder recorder = new Recorder();
                recorder.setAgentId(agentId);                               //终端编号
                recorder.setShelfId(secondaryShelfId);                      //货架编号
                recorder.setBatchNumber(StringUtils.generateUUID());        //设置batchNumber
                recorder.setOperate(0);                                     //减货操作
                recorder.setGoodsId(goods.getGoodsId());                    //商品编号
                recorder.setTotal(Integer.parseInt(stocks[0]));             //总量
                recorder.setAmount(0);                                      //现存量
                recorder.setRemain(StringUtils.arrayToString(remain, Constants.CsMessageSeperator.semicolon));
                recorderService.insert(recorder);
            }
        }
    }

}
